using Sirenix.OdinInspector;
using Tools.UI.InputEvent;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;

namespace Tools.UI
{
    public class OnUIDragPenetrate : MonoBehaviour
    {
        [SerializeField] OnUIDrag onDragger;
        [SerializeField] GameObject receiveTarget;
        [SerializeField] Axis selfStartAxis = Axis.Any;
        
        [SerializeField]
        UnityEvent<OnUIDrag,PointerEventData> onDragReady = new UnityEvent<OnUIDrag,PointerEventData>();
        public UnityEvent<OnUIDrag,PointerEventData> OnDragReady => onDragReady;
        
        [SerializeField]
        UnityEvent<OnUIDrag,PointerEventData> onDragEnd = new UnityEvent<OnUIDrag,PointerEventData>();
        public UnityEvent<OnUIDrag,PointerEventData> OnDragEnd => onDragEnd;
        
        [SerializeField]
        UnityEvent<OnUIDrag,PointerEventData>onDragging = new UnityEvent<OnUIDrag,PointerEventData>();
        public UnityEvent<OnUIDrag,PointerEventData> OnDragging => onDragging;
        
        Vector2 _downPosition;

        [SerializeField][ReadOnly]
        private int sendWay = 0;

        private void Awake()
        {
            onDragger.OnDragReady.AddListener(OnDragReadyFunc);
            onDragger.OnDragging.AddListener(OnDraggingFunc);
            onDragger.OnDragEnd.AddListener(OnDragEndFunc);
        }

        private void OnDragReadyFunc(OnUIDrag onDrag,PointerEventData eventData)
        {
            _downPosition = eventData.position;
        }
        
        private void OnDraggingFunc(OnUIDrag onDrag, PointerEventData eventData)
        {
            if (sendWay == 0)
            {
                if (selfStartAxis == Axis.Horizontal)
                {
                    sendWay = Mathf.Abs(eventData.delta.x) > Mathf.Abs(eventData.delta.y) ? 1 : 2;
                }
                else if (selfStartAxis == Axis.Vertical)
                {
                    sendWay = Mathf.Abs(eventData.delta.x) < Mathf.Abs(eventData.delta.y) ? 1 : 2;
                }
                else
                {
                    sendWay = 1;
                }

                if (sendWay == 1)
                {
                    OnDragReady?.Invoke(onDragger, eventData);
                }
                else if (sendWay == 2)
                {
                    ExecuteEvents.Execute(receiveTarget, eventData, ExecuteEvents.pointerDownHandler);
                    ExecuteEvents.Execute(receiveTarget, eventData, ExecuteEvents.beginDragHandler);
                }
            }

            if (sendWay == 1)
            {
                OnDragging?.Invoke(onDragger, eventData);
            }
            else if (sendWay == 2)
            {
                ExecuteEvents.Execute(receiveTarget, eventData, ExecuteEvents.dragHandler);
            }
        }

        private void OnDragEndFunc(OnUIDrag onDrag, PointerEventData eventData)
        {
            if (sendWay == 1)
            {
                OnDragEnd?.Invoke(onDragger, eventData);
            }
            else if (sendWay == 2)
            {
                ExecuteEvents.Execute(receiveTarget, eventData, ExecuteEvents.endDragHandler);
            }

            sendWay = 0;
        }
        #if UNITY_EDITOR
        void Reset()
        {
            onDragger = gameObject.GetComponent<OnUIDrag>();
        }
        #endif
    }
}
